<?

/**
 * Eventos class
 *
 * Esta clase maneja los eventos
 * @author Alejandro Garcia del Rio <alejandro.garciadelrio@elserver.com>
 * @version 1.0
 * @package Eventos
*/
class Eventos extends Core {

	static protected $instancia;
	static protected $opciones = array(
		'limit' => 10, // Cantidad de resultados 
	);

	/**
	 * Constructor de la clase.
	 * 
	 * @param integer $id_caso (opcional) El id de este caso.
	 * @param array $opciones (opcional) Opciones validas para esta clase
	 */
	function __construct ($id_caso=null, $opciones=null) {
		// Llamo al constructor del parent tambien
		parent::__construct();
		// Guardo las opciones si me definio alguna
		if ($opciones)
			$this->opciones($opciones);
	}

	/**
	 * Setea las opciones 
	 * 
	 * @param array $opciones (opcional) Opciones validas para esta clase. Si esta vacio, funciona como un getter.
	 * @return array $opciones Listado de opciones
	 */
	public function opciones ($opciones=null) {
		return self::$opciones = parent::opciones(self::$opciones, $opciones);
	}

	/**
	 * Devuelve una unica instancia de esta clase
	 * 
	 * @return object Instancia de esta clase
	 */
	public static function getInstance() {
		if (!self::$instancia instanceof self)
			self::$instancia = new self;
		return self::$instancia;
	}

	/**
	 * Devuelve el listado de eventos pendientes
	 * 
	 * @param array $opciones (opcional) Opciones validas para esta clase.
	 * @return array El listado de eventos pendientes
	 */
	public function pendientes ($opciones=null) {

		// Obtengo el objeto de base de datos
		$db = ($this)? $this->db : ez_sql::getInstance();

		// Seteo las opciones
		$opciones = ($this instanceof self)? $this->opciones($opciones) : self::opciones($opciones);

		// Obtengo los eventos pendientes 
		$pendientes = $db->get_results("SELECT * FROM eventos WHERE hecho = 0 AND exec_time IS NOT NULL AND exec_time <= NOW() ORDER BY exec_time ASC");

		return $pendientes;
	}
	
	/**
	 * Agrega un evento
	 * 
	 * @param array $caso Informacion del evento a crear
	 * @return integer Id del evento creado
	 */
	public function agregar ($evento) {
		
		// Me aseguro que no se modifiquen algunos campos
		unset($evento['id_evento']);
		unset($evento['hecho']);
		unset($evento['ctime']);
		unset($evento['error']);

		// Serializo los parametros
		if ($evento['params'])
			$evento['params'] = serialize($evento['params']);

		// Obtengo el objeto de base de datos
		$db = ($this)? $this->db : ez_sql::getInstance();

		// Agrego el evento
		$id_evento = $db->insert('eventos', $evento);
		
		return $id_evento;
	}
	
	/**
	 * Elimina un evento
	 * 
	 * @param integer $id_evento El id del evento a eliminar
	 * @return boolean
	 */
	public function eliminar ($id_evento) {
		
		// Saneamiento de variables
		$id_evento = addslashes($id_evento);

		// Obtengo el objeto de base de datos
		$db = ($this)? $this->db : ez_sql::getInstance();

		// Me fijo que el evento no este hecho
		$evento = self::get($id_evento);
		if ($evento['hecho'] == 1)
			return ($this)? $this->fail('El evento no se puede eliminar porque ya fue ejecutado') : false;

		// Elimino el evento
		$db->query("DELETE FROM eventos WHERE id_evento = '$id_evento' LIMIT 1");
		
		return true;
	}
	
	/**
	 * Modifica un evento
	 * 
	 * @param integer $id_evento El id del evento a eliminar
	 * @param integer $evento La nueva informacion del evento
	 * @return boolean
	 */
	public function modificar ($id_evento, $evento) {

		// Me aseguro que no se modifiquen algunos campos
		unset($evento['id_evento']);
		unset($evento['hecho']);
		unset($evento['ctime']);
		unset($evento['error']);

		// Serializo los parametros
		if ($evento['params'])
			$evento['params'] = serialize($evento['params']);

		// Obtengo el objeto de base de datos
		$db = ($this)? $this->db : ez_sql::getInstance();

		// Me fijo que el evento no este hecho
		$evento = self::get($id_evento);
		if ($evento['hecho'] == 1)
			return ($this)? $this->fail('El evento no se puede modificar porque ya fue ejecutado') : false;

		// Modifico el evento
		$id_evento = $db->update('eventos', array_merge($evento, array('id_evento' => $id_evento)));
		
		return true;
	}

	/**
	 * Marca un evento como hecho
	 * 
	 * @param integer $id_evento El id del evento que se ejecuto
	 * @return boolean
	 */
	public function hecho ($id_evento) {

		// Saneamiento de variables
		$id_evento = addslashes($id_evento);

		// Obtengo el objeto de base de datos
		$db = ($this)? $this->db : ez_sql::getInstance();

		// Marco el evento como hecho
		$db->update('eventos', array('id_evento' => $id_evento, 'hecho' => 1));
		
		return true;
	}

	/**
	 * Marca un evento como fallido
	 * 
	 * @param integer $id_evento El id del evento que fallo
	 * @param string $error (Opcional) El error por el cual no se pudo ejecutar la funcion
	 * @return boolean
	 */
	public function failed ($id_evento, $error='') {

		// Saneamiento de variables
		$id_evento = addslashes($id_evento);

		// Obtengo el objeto de base de datos
		$db = ($this)? $this->db : ez_sql::getInstance();

		// Marco el evento como fallido
		$db->update('eventos', array('id_evento' => $id_evento, 'hecho' => '-1', 'error' => $error));
		
		return true;
	}

	/**
	 * Devuelve la informacion de un evento
	 * 
	 * @param integer $id_evento El id del evento del que se quiere la informacion
	 * @return array
	 */
	public function get ($id_evento) {

		// Saneamiento de variables
		$id_evento = addslashes($id_evento);

		// Obtengo el objeto de base de datos
		$db = ($this)? $this->db : ez_sql::getInstance();

		// Obtengo la informacion del evento
		$evento = $db->get_row("SELECT * FROM eventos WHERE id_evento = '$id_evento'");

		// Deserializo los parametros
		if ($evento['params'])
			$evento['params'] = unserialize($evento['params']);
		
		return $evento;
	}
	
	/**
	 * Ejecuta un evento
	 * 
	 * @param integer $id_evento El id del evento que se quiere ejecutar
	 * @return boolean
	 */
	public function execute ($id_evento) {

		// Saneamiento de variables
		$id_evento = addslashes($id_evento);

		// Obtengo el objeto de base de datos
		$db = ($this)? $this->db : ez_sql::getInstance();

		// Obtengo la informacion del evento
		$evento = self::get($id_evento);

		// Instancio la clase
		$obj = new $evento['class']();
		
		// Trato de ejecutar el evento
		if (call_user_func_array(array($obj, $evento['method']), (array)$evento['params'])) {
			self::hecho($evento['id_evento']);
			return true;
		}

		// Algo salio mal, primero obtengo el error
		$error = $obj->error();

		// Marco el evento como fallido 
		self::failed($evento['id_evento'], $error);

		return ($this)? $this->fail('No se pudo ejecutar el evento: '.$error) : false;
	}

}

?>
